package com.example.aop;

import com.alibaba.fastjson.JSONObject;
import com.example.mapper.OperateLogMapper;
import com.example.pojo.OperateLog;
import com.example.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.util.Arrays;

//切面类 给方法增加新功能
@Component
@Slf4j
@Aspect //切面类的注解
public class LOgAspect {

    @Autowired
    private HttpServletRequest Request;
    @Autowired
    private OperateLogMapper operateLogMapper;

    //annotation注解 加环绕
    @Around("@annotation(com.example.anno.Log)")
    public Object recordLog(ProceedingJoinPoint JoinPoint) throws Throwable {
        //根据要求要增加以下功能

        //1.操作人的id
        /*通过令牌来获取登录人的id
        获取请求头中的令牌（token）--方法req.getHeader
        String Jwt = req.getHeader("token");
        此时就需要一个类型 HttpServletRequest 注入。。 */
        String jwt = Request.getHeader("token");
        //解析令牌
        Claims claims = JwtUtils.parseJWT(jwt);
        //获取令牌的id
        Integer operateUser =(Integer) claims.get("id");

        //2.操作时间
        LocalDateTime operateTime = LocalDateTime.now();

        //3.操作类名
        /*通过aop 参数的方法获取
        * getClass() 获取类对象
        * getName() 获取类名*/
        String classname = JoinPoint.getClass().getName();

        //4.操作的方法名
        /*通过aop 参数的方法获取
         * getSignature() 获取方法的签名
         * getName() 获取方法名*/
        String methodName = JoinPoint.getSignature().getName();

        //5.操作方法的参数
        /*通过aop 参数的方法获取
         * getArgs() 返回值是一个数组
         * Arrays.toString(args) 转为字符串*/
        Object[] args = JoinPoint.getArgs();
        String methodParams = Arrays.toString(args);

        //6.操作方法的返回值
        //返回值就是result
        //调用原始方法
        long begin = System.currentTimeMillis();
        Object result = JoinPoint.proceed();
        /* 可以将result对象转换为Json格式的字符串保存起来
        *JSONObject.toJSONString(result) 对象转Json格式 */
        String returnValue = JSONObject.toJSONString(result);

        //7.操作的耗时
        long end = System.currentTimeMillis();
        Long costTime = end -begin;


        //执行完方法之后 还要执行操作日志
        OperateLog OperateLog = new OperateLog(null,operateUser,operateTime,classname,methodName,methodParams,returnValue,costTime); //new一个 有参构造
        operateLogMapper.insert(OperateLog); //调用这个方法。需要传入一个参数 类型为OperateLog

        log.info("AOP记录操作日志：{}",OperateLog);
        //返回类型是Object
        return result;
    }
}
